//
//  CTVClipInChannelParser.m
//  Channltv
//
//  Created by Bruno Keymolen on 03/09/07.
//  Copyright 2007 channl.tv. All rights reserved.
//

#import "CTVClipInChannelParser.h"
#import "CTVClip.h";
#import "CTVCache.h"
#import "CTVChannel.h"

@implementation CTVClipInChannelParser

-(id)init{
	[super init];
	
	
	m_clips = [[NSMutableArray alloc] init]; //CTVClip collection
	
	return self;	
}

-(void)dealloc{
	[self _releaseClips];
	[m_clips release];
	
	[super dealloc];
	
}

-(NSArray*)clips{
	return m_clips;
}

-(int)parseFromData:(NSData*)data orderNewestFirst:(BOOL)order{
	int ret = 0;
	[self _releaseClips]; //empty the eventually previous collection

	NSXMLDocument* xmlDoc;

	NSError *err=nil;	
	xmlDoc = [[NSXMLDocument alloc] initWithData:data options:(NSXMLNodePreserveWhitespace|NSXMLNodePreserveCDATA) error:&err]; 
	
	if(xmlDoc == nil){
		ret -1;
		NSLog(@"Error, CTVClipInChannelParser. Could not parse"); 		
	}else{
		//clip-s
		NSArray* clipCollection = [xmlDoc nodesForXPath:@"//rss/channel/item" error:&err];

		int clipt, clipcnt, childt, childcnt;
		clipcnt = [clipCollection count];
		NSXMLNode* aNode; 
		NSXMLNode* clipNode;
		CTVClip* prog;

		
		//Cycle through clips
		for(clipt=0;clipt<clipcnt;clipt++){
			clipNode = [clipCollection objectAtIndex:clipt];
			
			prog = [[CTVClip alloc] init];
			if(order){ //newest first ?
				[m_clips addObject:prog];
			}else{
				[m_clips insertObject:prog atIndex:0]; 
			}
			//Cycle through childs of clip
			childcnt = [clipNode childCount];
			for (childt=0;childt<childcnt;childt++) {
				
				aNode = [clipNode childAtIndex:childt];
				if([aNode kind] == NSXMLElementKind) {

					NSString* sVal = [NSString stringWithString:[aNode stringValue]];
					NSString* oVal = [NSString stringWithString:[aNode name]];

					if (sVal != nil) {
						if( [oVal caseInsensitiveCompare:@"title"] == NSOrderedSame){
							//Title
							if(![sVal isEmpty])[prog setTitle:sVal]; //copy the title to the memory slot for this program
						}else if( [oVal caseInsensitiveCompare:@"media:thumbnail"] == NSOrderedSame){
							//Thumnnail
							NSXMLElement* xmlElement = (NSXMLElement*)aNode; //NSXMLElement is derived from NSXMLNode
							aNode = [xmlElement attributeForName:@"url"];
							sVal = [aNode stringValue];						
							[prog setThumbUrl:sVal];
						}else if( [oVal caseInsensitiveCompare:@"link"] == NSOrderedSame){
							//URL
							if(![sVal isEmpty])[prog setUrl:sVal]; 
						}else if( [oVal caseInsensitiveCompare:@"guid"] == NSOrderedSame){
							//clip ID
							if(![sVal isEmpty])[prog setClipID:sVal];
						}else if( [oVal caseInsensitiveCompare:@"description"] == NSOrderedSame){
							//Info
							[prog setInfo:sVal]; //can be empty ""
						}else if( [oVal caseInsensitiveCompare:@"media:duration"] == NSOrderedSame){
							//Duration
							NSXMLElement* xmlElement = (NSXMLElement*)aNode; //NSXMLElement is derived from NSXMLNode
							aNode = [xmlElement attributeForName:@"seconds"];
							if(aNode){
								sVal = [aNode stringValue];						
								[prog setDuration:atoi([sVal UTF8String])];
							}
						}else if( [oVal caseInsensitiveCompare:@"channltv:rating"] == NSOrderedSame){
							//Rate
							NSXMLElement* xmlElement = (NSXMLElement*)aNode; //NSXMLElement is derived from NSXMLNode
							aNode = [xmlElement attributeForName:@"calculated_rate"];
							if(aNode){
								sVal = [aNode stringValue];		
								[prog setRate:atof([sVal UTF8String])];
							} 			
							//Rate Count
							aNode = [xmlElement attributeForName:@"rate_count"];
							if(aNode){
								sVal = [aNode stringValue];		
								[prog setRateCount:atoi([sVal UTF8String])]; 		
							}
							//Viewer rate
							aNode = [xmlElement attributeForName:@"viewer_rate"];
							if(aNode){
								sVal = [aNode stringValue];		
								[prog setViewerRate:atof([sVal UTF8String])];
							} 											
						}else if( [oVal caseInsensitiveCompare:@"media:stream"] == NSOrderedSame){
							//Stream
							NSXMLElement* xmlElement = (NSXMLElement*)aNode; //NSXMLElement is derived from NSXMLNode
							aNode = [xmlElement attributeForName:@"value"];
							sVal = [aNode stringValue];						
							if(aNode){
								if([sVal compare:@"1"] == NSOrderedSame){
									[prog setStreamMedia:TRUE];
								}else{
									[prog setStreamMedia:FALSE];
								}
							}
						}else if( [oVal caseInsensitiveCompare:@"media:sync"] == NSOrderedSame){
							//Sync
							NSXMLElement* xmlElement = (NSXMLElement*)aNode; //NSXMLElement is derived from NSXMLNode
							aNode = [xmlElement attributeForName:@"value"];
							if(aNode){
								sVal = [aNode stringValue];						
								if([sVal compare:@"1"] == NSOrderedSame){
									[prog setAutoSyncMedia:TRUE];
								}else{
									[prog setAutoSyncMedia:FALSE];
								}
							}
						}else if( [oVal caseInsensitiveCompare:@"media:keepprivate"] == NSOrderedSame){
							//Private
							NSXMLElement* xmlElement = (NSXMLElement*)aNode; //NSXMLElement is derived from NSXMLNode
							aNode = [xmlElement attributeForName:@"value"];
							if(aNode){
								sVal = [aNode stringValue];						
								if([sVal compare:@"1"] == NSOrderedSame){
									[prog setPrivateMedia:TRUE];
								}else{
									[prog setPrivateMedia:FALSE];
								}
							}
						}						
						
					}				
				}
			}
			//Sanity check, otherwise; remove clip
			if(![prog isSane]){
				[m_clips removeObject:prog];
				[prog release];
			}		
		}
		

	}
	
	[xmlDoc release];
	
	return ret;
}


-(int)parseFromPath:(NSString*)path orderNewestFirst:(BOOL)order{
	int ret = 0;
	
	//Read the data from the file
	NSData* data = [NSData dataWithContentsOfFile:path];
	if(data == nil){
		NSLog(@"Error, CTVClipInChannelParser. Could not read data from file %@", path); 
		ret -1;
	}else{
		ret = [self parseFromData:data orderNewestFirst:order];
	}
	
	return ret;

}


//Private
-(void)_releaseClips{
	CTVClip* clip;
	NSEnumerator* enumerator = [m_clips objectEnumerator];
	while (clip = [enumerator nextObject]) {
		[clip release]; //because we allocated (retain must be used outside this class if the channels should stay in memory)
	}
	[m_clips removeAllObjects];
}


@end
